package com.sinping.qh.utils.word;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.apache.poi.util.DocumentHelper;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.Document;
import org.junit.Test;

import javax.lang.model.element.Element;
import java.io.*;
import java.util.*;

/**
 * @author jiahuaiqing
 * @create 2018/7/11
 */
public class DocumentHandler {
    private Configuration configuration = null;

    public DocumentHandler() {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    }

    public void createDoc(String templateName, Map<String, Object> dataMap, String fileName) throws UnsupportedEncodingException {
        //dataMap 要填入模本的数据文件
        //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet，classpath，数据库装载，
        //这里我们的模板是放在template包下面
        configuration.setClassForTemplateLoading(this.getClass(), "/template");
        Template t = null;
        try {
            //test.ftl为要装载的模板
            t = configuration.getTemplate(templateName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出文档路径及名称
        File outFile = new File(fileName);
        Writer out = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
            //这个地方对流的编码不可或缺，使用main（）单独调用时，应该可以，但是如果是web请求导出时导出后word文档就会打不开，并且包XML文件错误。主要是编码格式不正确，无法解析。
            //out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            out = new BufferedWriter(oWriter);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        try {
            t.process(dataMap, out);
            out.close();
            fos.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * window 环境下使用
     * <p>
     * FreeMarker通过xml结构生成Word文档，在移动端打开却显示的是xml文档，PC打开正常，
     * 而PC上使用Office或者Wps打开这个文档，另存为一个新的Word文档，在移动端打开就正常了。
     * 顺着这个思路，找到一个解决方案，使用JACOB - Java COM Bridge download，
     * 通过Java代码把FreeMarker生成文档另存为一个新的Word文档
     *
     * @param oldPath 原文件路径
     * @param newPath 新文件路径
     */
    public static void createNewWordDoc(String oldPath, String newPath) {
        ActiveXComponent _app = new ActiveXComponent("Word.Application");
        _app.setProperty("Visible", Variant.VT_FALSE);
        Dispatch documents = _app.getProperty("Documents").toDispatch();
        // 打开FreeMarker生成的Word文档  oldPath="原文件路径/oldname.doc" newPath="新文件路径/name.doc"
        Dispatch doc = Dispatch.call(documents, "Open", oldPath, Variant.VT_FALSE, Variant.VT_TRUE).toDispatch();
        // 另存为新的Word文档
        Dispatch.call(doc, "SaveAs", newPath, Variant.VT_FALSE, Variant.VT_TRUE);

        Dispatch.call(doc, "Close", Variant.VT_FALSE);
        _app.invoke("Quit", new Variant[]{});
        ComThread.Release();
    }

    /**
     * docx文档转换为PDF
     *
     * @param pdfPath PDF文档存储路径
     * @throws Exception 可能为Docx4JException, FileNotFoundException, IOException等
     */
    public static void convertDocxToPDF(String docxPath, String pdfPath) throws Exception {
        OutputStream os = null;
        try {
            InputStream is = new FileInputStream(new File(docxPath));
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
            Mapper fontMapper = new IdentityPlusMapper();
            fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
            fontMapper.put("宋体",PhysicalFonts.get("SimSun"));
            fontMapper.put("微软雅黑",PhysicalFonts.get("Microsoft Yahei"));
            fontMapper.put("黑体",PhysicalFonts.get("SimHei"));
            fontMapper.put("楷体",PhysicalFonts.get("KaiTi"));
            fontMapper.put("新宋体",PhysicalFonts.get("NSimSun"));
            fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
            fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
            fontMapper.put("宋体扩展",PhysicalFonts.get("simsun-extB"));
            fontMapper.put("仿宋",PhysicalFonts.get("FangSong"));
            fontMapper.put("仿宋_GB2312",PhysicalFonts.get("FangSong_GB2312"));
            fontMapper.put("幼圆",PhysicalFonts.get("YouYuan"));
            fontMapper.put("华文宋体",PhysicalFonts.get("STSong"));
            fontMapper.put("华文中宋",PhysicalFonts.get("STZhongsong"));

            mlPackage.setFontMapper(fontMapper);

            os = new java.io.FileOutputStream(pdfPath);

            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

        }catch(Exception ex){
            ex.printStackTrace();
        }finally {
            IOUtils.closeQuietly(os);
        }
    }




    @Test
    public void outDocument() throws UnsupportedEncodingException {
        List<String> strings = new ArrayList<>();
        strings.add("aa");
        strings.add("aab");
        strings.add("aac");
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("noticeBookNo", "+AHQ12345679");
        dataMap.put("String", strings);
        dataMap.put("unitName", "清华大学");
        //dataMap.put("offices", "123");
        dataMap.put("sendDate", "2017年12月");
        dataMap.put("gmt_created", "2017-12-10 08:12:56");
        dataMap.put("hiddendesc", "123456789");
        dataMap.put("image_url", "123");
        dataMap.put("desc", "123");
        dataMap.put("create_user_name", "123");
        dataMap.put("submit_user_name", "张三李四");
        dataMap.put("submit_time", "123");
        dataMap.put("building_name", "123");
        dataMap.put("room_no", "123");
        dataMap.put("lab_name", "123");
        dataMap.put("risk_manager", "王强");
        dataMap.put("risk_level", "B");

        // /生成word文档
        DocumentHandler documentHandler = new DocumentHandler();
        //documentHandler.createDoc(dataMap,"E:/outFile.doc");
    }
}
